    /**
    * Video Chat Module
    * Handles WebRTC video calling functionality through WebSocket signaling
    */
    const videoChatModule = (function() {
    // WebRTC configuration
    const configuration = {
    iceServers: [
{ urls: "stun:117.50.221.81:3478" },
{
    urls: "turn:117.50.221.81:3478",
    username: "username",         // ✅ 仅用户名
    credential: "password"  // ✅ 与服务器配置一致
}
    ]
};

    // Variables
    let localStream = null;
    let remoteStream = null;
    let peerConnection = null;
    let socket = null;
    let currentCallData = null;
    let isCallInProgress = false;
    let localVideo = null;
    let remoteVideo = null;
    let isFullscreen = false;
    let isVideosSwapped = false;
    let controlsTimer = null;
    let isControlsHidden = false;
    let isMouseMoving = false;
    let lastMouseMoveTime = Date.now();

    // DOM Elements
    let videoCallModal = null;
    let videoCallHeader = null;
    let callControls = null;
    let localVideoContainer = null;
    let remoteVideoContainer = null;

    /**
     * Initialize the video chat module
     */
    function init(userId) {
    console.log('Initializing video chat module for user:', userId);
    createVideoCallInterface();

    // Connect to WebSocket for video chat signaling
    connectWebSocket(userId);

    // Bind video call buttons in chat interface
    bindVideoCallButtons();
}

    /**
     * Connect to WebSocket for video chat signaling
     */
    function connectWebSocket(userId) {
    if (!userId) {
    console.error('Cannot connect WebSocket: Missing user ID');
    return;
}

    const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    const wsUrl = `${wsProtocol}//${window.location.host}/RemoteAddressForVideoChat?username=${userId}`;

    socket = new WebSocket(wsUrl);

    socket.onopen = function() {
    console.log('Video chat WebSocket connection established');
};

    socket.onmessage = function(event) {
    const message = JSON.parse(event.data);
    console.log('Video chat WebSocket message received:', message);

    // Handle different message types
    switch(message.type) {
    case 'call_start':
    handleIncomingCall(message);
    break;
    case 'call_back':
    handleCallResponse(message);
    break;
    case 'offer':
    handleOffer(message);
    break;
    case 'answer':
    handleAnswer(message);
    break;
    case '_ice':
    handleIceCandidate(message);
    break;
    case 'hangup':
    handleHangup(message);
    break;
    default:
    console.log('Unknown message type:', message.type);
}
};

    socket.onclose = function() {
    console.log('Video chat WebSocket connection closed');
};

    socket.onerror = function(error) {
    console.error('Video chat WebSocket error:', error);
};
}

    /**
     * Create the video call interface modal
     */
    function createVideoCallInterface() {
    // Create modal if it doesn't exist
    if (document.getElementById('video-call-modal')) {
    videoCallModal = document.getElementById('video-call-modal');
    setupUIControls();
    return;
}

    videoCallModal = document.createElement('div');
    videoCallModal.id = 'video-call-modal';
    videoCallModal.className = 'video-call-modal';

    videoCallModal.innerHTML = `
            <div class="video-call-container">
                <div class="video-call-header">
                    <div class="call-info">
                        <div class="call-avatar">
                            <img src="/images/avatar.png" id="call-avatar-img" alt="Contact">
                        </div>
                        <div class="call-details">
                            <h3 id="call-contact-name">联系人</h3>
                            <span id="call-status">正在通话...</span>
                        </div>
                    </div>
                    <div class="call-actions">
                        <button id="fullscreen-toggle" class="call-action-btn" title="全屏切换">
                            <i class="fas fa-expand"></i>
                            <i class="fas fa-compress"></i>
                        </button>
                    </div>
                    <div class="call-timer" id="call-timer">00:00</div>
                </div>

                <div class="video-container">
                    <div class="remote-video-container">
                        <video id="remote-video" autoplay playsinline></video>
                    </div>
                    <div class="local-video-container">
                        <video id="local-video" autoplay playsinline muted></video>
                    </div>
                </div>

                <div class="call-controls" id="ongoing-call-controls">
                    <button class="call-control-btn" id="toggle-mic" title="静音">
                        <i class="fas fa-microphone"></i>
                    </button>
                    <button class="call-control-btn" id="toggle-video" title="关闭视频">
                        <i class="fas fa-video"></i>
                    </button>
                    <button class="call-control-btn" id="toggle-screen-share" title="屏幕共享">
                        <i class="fas fa-desktop"></i>
                    </button>
                    <button class="call-control-btn" id="switch-camera" title="切换摄像头">
                        <i class="fas fa-sync"></i>
                    </button>
                    <button class="call-control-btn fullscreen-toggle" id="fullscreen-toggle-control" title="全屏切换">
                        <i class="fas fa-expand"></i>
                        <i class="fas fa-compress"></i>
                    </button>
                    <button class="call-control-btn end-call" id="end-call" title="结束通话">
                        <i class="fas fa-phone-slash"></i>
                    </button>
                </div>

                <div class="call-controls" id="incoming-call-controls">
                    <button class="call-control-btn accept-call" id="accept-call" title="接听">
                        <i class="fas fa-phone"></i>
                    </button>
                    <button class="call-control-btn reject-call" id="reject-call" title="拒绝">
                        <i class="fas fa-phone-slash"></i>
                    </button>
                </div>
            </div>
        `;

    document.body.appendChild(videoCallModal);

    // Get video elements
    localVideo = document.getElementById('local-video');
    remoteVideo = document.getElementById('remote-video');

    // Setup event listeners for call controls
    document.getElementById('toggle-mic').addEventListener('click', toggleMicrophone);
    document.getElementById('toggle-video').addEventListener('click', toggleVideo);
    document.getElementById('toggle-screen-share').addEventListener('click', toggleScreenShare);
    document.getElementById('switch-camera').addEventListener('click', switchCamera);
    document.getElementById('end-call').addEventListener('click', endCall);
    document.getElementById('accept-call').addEventListener('click', acceptCall);
    document.getElementById('reject-call').addEventListener('click', rejectCall);

    // Setup additional UI controls like fullscreen and auto-hide
    setupUIControls();
}

    /**
     * Setup UI controls for fullscreen, video swapping, and auto-hiding
     */
    function setupUIControls() {
    // Store DOM elements for easy access
    videoCallHeader = document.querySelector('.video-call-header');
    callControls = document.querySelectorAll('.call-controls');
    localVideoContainer = document.querySelector('.local-video-container');
    remoteVideoContainer = document.querySelector('.remote-video-container');

    // Setup fullscreen toggle buttons
    const fullscreenToggleBtns = document.querySelectorAll('#fullscreen-toggle, #fullscreen-toggle-control');
    fullscreenToggleBtns.forEach(btn => {
    btn.addEventListener('click', toggleFullscreen);
});

    // Setup video swap on local video click
    if (localVideoContainer) {
    localVideoContainer.addEventListener('click', swapVideos);
}

    // Setup mouse move detection for auto-hide controls
    videoCallModal.addEventListener('mousemove', handleMouseMove);

    // Listen for ESC key to exit fullscreen
    document.addEventListener('keydown', function(e) {
    if (e.key === 'Escape' && isFullscreen) {
    toggleFullscreen();
}
});

    // Handle call modal opening to reset controls state
    videoCallModal.addEventListener('call-started', function() {
    showControls();
    startControlsTimer();
});

    // Reset controls visibility on call end
    videoCallModal.addEventListener('call-ended', function() {
    clearControlsTimer();
    showControls();
    resetFullscreen();
    resetVideoSwap();
});
}

    /**
     * Handle mouse movement to show controls
     */
    function handleMouseMove() {
    lastMouseMoveTime = Date.now();
    isMouseMoving = true;

    if (isControlsHidden) {
    showControls();
}

    // If we don't have a timer yet, start one
    if (!controlsTimer && isCallInProgress) {
    startControlsTimer();
}
}

    /**
     * Start controls auto-hide timer
     */
    function startControlsTimer() {
    clearControlsTimer(); // Clear any existing timer

    controlsTimer = setInterval(() => {
    const currentTime = Date.now();
    // If mouse hasn't moved for 3 seconds, hide the controls
    if (currentTime - lastMouseMoveTime > 3000 && isCallInProgress) {
    hideControls();
}
}, 1000);
}

    /**
     * Clear controls auto-hide timer
     */
    function clearControlsTimer() {
    if (controlsTimer) {
    clearInterval(controlsTimer);
    controlsTimer = null;
}
}

    /**
     * Show header and controls
     */
    function showControls() {
    isControlsHidden = false;
    if (videoCallHeader) {
    videoCallHeader.classList.remove('hidden');
}

    callControls.forEach(control => {
    control.classList.remove('hidden');
});
}

    /**
     * Hide header and controls
     */
    function hideControls() {
    isControlsHidden = true;
    if (videoCallHeader) {
    videoCallHeader.classList.add('hidden');
}

    callControls.forEach(control => {
    control.classList.add('hidden');
});
}

    /**
     * Toggle fullscreen mode
     */
    function toggleFullscreen() {
    isFullscreen = !isFullscreen;

    if (isFullscreen) {
    videoCallModal.classList.add('fullscreen');

    // Try to request browser fullscreen if supported
    if (videoCallModal.requestFullscreen) {
    videoCallModal.requestFullscreen();
} else if (videoCallModal.webkitRequestFullscreen) {
    videoCallModal.webkitRequestFullscreen();
} else if (videoCallModal.msRequestFullscreen) {
    videoCallModal.msRequestFullscreen();
}
} else {
    videoCallModal.classList.remove('fullscreen');

    // Exit browser fullscreen if active
    if (document.exitFullscreen) {
    document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
    document.msExitFullscreen();
}
}

    // Trigger resize event to adjust video layout
    window.dispatchEvent(new Event('resize'));
}

    /**
     * Reset fullscreen mode
     */
    function resetFullscreen() {
    if (isFullscreen) {
    isFullscreen = false;
    videoCallModal.classList.remove('fullscreen');

    // Exit browser fullscreen if active
    if (document.exitFullscreen) {
    document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
    document.msExitFullscreen();
}
}
}

    /**
     * Swap local and remote videos
     */
    function swapVideos() {
    isVideosSwapped = !isVideosSwapped;

    if (isVideosSwapped) {
    localVideoContainer.classList.add('swapped');
    remoteVideoContainer.classList.add('swapped');
} else {
    localVideoContainer.classList.remove('swapped');
    remoteVideoContainer.classList.remove('swapped');
}
}

    /**
     * Reset video swap state
     */
    function resetVideoSwap() {
    if (isVideosSwapped) {
    isVideosSwapped = false;
    localVideoContainer.classList.remove('swapped');
    remoteVideoContainer.classList.remove('swapped');
}
}

    /**
     * Bind video and voice call buttons in chat interface
     */
    function bindVideoCallButtons() {
    // Find all call buttons in the chat interface
    document.addEventListener('click', function(event) {
    // Video call button
    const videoCallBtn = event.target.closest('.chat-actions .btn-icon[title="视频通话"], #video-call-btn');
    if (videoCallBtn) {
    const chatHeader = videoCallBtn.closest('.chat-header');
    if (chatHeader) {
    const contactName = chatHeader.querySelector('#chat-contact-name').textContent;
    const contactId = currentChatUserId; // This comes from messages.js

    if (contactId) {
    initiateVideoCall(contactId, contactName);
} else {
    console.error('Cannot initiate call: Contact ID not found');
}
}
}

    // Voice call button (video disabled)
    const voiceCallBtn = event.target.closest('.chat-actions .btn-icon[title="语音通话"], #voice-call-btn');
    if (voiceCallBtn) {
    const chatHeader = voiceCallBtn.closest('.chat-header');
    if (chatHeader) {
    const contactName = chatHeader.querySelector('#chat-contact-name').textContent;
    const contactId = currentChatUserId; // This comes from messages.js

    if (contactId) {
    // Voice call is just a video call with video disabled
    initiateVoiceCall(contactId, contactName);
} else {
    console.error('Cannot initiate call: Contact ID not found');
}
}
}
});
}

    /**
     * Initiate a voice call (video call with video disabled)
     */
    function initiateVoiceCall(contactId, contactName) {
    if (isCallInProgress) {
    alert('您已经在通话中，请先结束当前通话');
    return;
}

    console.log('Initiating voice call to:', contactId, contactName);

    // Store call data
    currentCallData = {
    toUser: contactId,
    fromUser: getCurrentUserId(),
    contactName: contactName,
    isVideoEnabled: false
};

    // Update UI for outgoing call
    document.getElementById('call-contact-name').textContent = contactName;
    document.getElementById('call-status').textContent = '正在语音呼叫...';
    document.getElementById('call-avatar-img').src = getSenderAvatar(contactId);

    // Show outgoing call UI
    document.getElementById('ongoing-call-controls').style.display = 'flex';
    document.getElementById('incoming-call-controls').style.display = 'none';

    // Add voice call class to modify UI
    videoCallModal.classList.add('voice-call');

    // Show the call modal
    videoCallModal.classList.add('active');

    // Request user media (audio only) and start the call process
    navigator.mediaDevices.getUserMedia({
    audio: true,
    video: false
})
    .then(stream => {
    localStream = stream;
    localVideo.srcObject = stream;

    // Send call request through WebSocket
    sendWebSocketMessage({
    type: 'call_start',
    toUser: contactId.toString(),
    fromUser: getCurrentUserId().toString(),
    msg: '1',
    callType: 'voice'
});
})
    .catch(error => {
    console.error('Error accessing media devices:', error);
    showError('无法访问麦克风，请检查您的设备权限');
    endCall();
});
}

    /**
     * Initiate a video call to the specified contact
     */
    function initiateVideoCall(contactId, contactName) {
    if (isCallInProgress) {
    alert('您已经在通话中，请先结束当前通话');
    return;
}

    console.log('Initiating video call to:', contactId, contactName);

    // Remove any previous voice call class
    videoCallModal.classList.remove('voice-call');

    // Store call data
    currentCallData = {
    toUser: contactId,
    fromUser: getCurrentUserId(),
    contactName: contactName,
    isVideoEnabled: true
};

    // Update UI for outgoing call
    document.getElementById('call-contact-name').textContent = contactName;
    document.getElementById('call-status').textContent = '正在呼叫...';
    document.getElementById('call-avatar-img').src = getSenderAvatar(contactId);

    // Show outgoing call UI
    document.getElementById('ongoing-call-controls').style.display = 'flex';
    document.getElementById('incoming-call-controls').style.display = 'none';

    // Show the call modal
    videoCallModal.classList.add('active');

    // Request user media and start the call process
    getUserMedia()
    .then(() => {
    // Send call request through WebSocket
    sendWebSocketMessage({
    type: 'call_start',
    toUser: contactId.toString(),
    fromUser: getCurrentUserId().toString(),
    msg: '1',
    callType: 'video'
});
})
    .catch(error => {
    console.error('Error accessing media devices:', error);
    showError('无法访问摄像头或麦克风，请检查您的设备权限');
    endCall();
});
}

    /**
     * Handle incoming call
     */
    function handleIncomingCall(message) {
    if (isCallInProgress) {
    // Automatically reject if already in a call
    sendWebSocketMessage({
    type: 'call_back',
    toUser: message.fromUser,
    fromUser: getCurrentUserId().toString(),
    msg: 'busy'
});
    return;
}

    const callerId = message.fromUser;
    const callerName = getSenderName(callerId);
    const callType = message.callType || 'video';

    // Store call data
    currentCallData = {
    toUser: getCurrentUserId(),
    fromUser: callerId,
    contactName: callerName,
    isVideoEnabled: callType === 'video'
};

    // Apply voice call UI if it's a voice call
    if (callType === 'voice') {
    videoCallModal.classList.add('voice-call');
} else {
    videoCallModal.classList.remove('voice-call');
}

    // Play ring tone
    playCallSound('incoming');

    // Update UI for incoming call
    document.getElementById('call-contact-name').textContent = callerName;
    document.getElementById('call-status').textContent = callType === 'video' ? '视频来电...' : '语音来电...';
    document.getElementById('call-avatar-img').src = getSenderAvatar(callerId);

    // Show incoming call UI
    document.getElementById('ongoing-call-controls').style.display = 'none';
    document.getElementById('incoming-call-controls').style.display = 'flex';

    // Show the call modal
    videoCallModal.classList.add('active');

    // If we're in messages page, highlight the caller in the contacts list
    highlightCaller(callerId);
}

    /**
     * Highlight the caller in the contacts list
     */
    function highlightCaller(callerId) {
    const contactItem = document.querySelector(`.contact-item[data-id="${callerId}"]`);
    if (contactItem) {
    contactItem.classList.add('calling');

    // Remove the highlight when call ends
    const removeHighlight = () => {
    contactItem.classList.remove('calling');
    videoCallModal.removeEventListener('call-ended', removeHighlight);
};

    // Create a custom event listener for call end
    videoCallModal.addEventListener('call-ended', removeHighlight);
}
}

    /**
     * Accept an incoming call
     */
    function acceptCall() {
    if (!currentCallData) return;

    document.getElementById('call-status').textContent = '正在连接...';

    // Switch to ongoing call controls
    document.getElementById('ongoing-call-controls').style.display = 'flex';
    document.getElementById('incoming-call-controls').style.display = 'none';

    // Stop ringtone
    stopCallSound();

    // Get user media and create peer connection
    getUserMedia()
    .then(() => {
    createPeerConnection();

    // Send answer
    sendWebSocketMessage({
    type: 'call_back',
    toUser: currentCallData.fromUser.toString(),
    fromUser: getCurrentUserId().toString(),
    msg: 'accept'
});

    // Dispatch call-started event to initialize UI controls
    videoCallModal.dispatchEvent(new Event('call-started'));
})
    .catch(error => {
    console.error('Error accessing media devices:', error);
    showError('无法访问摄像头或麦克风，请检查您的设备权限');
    endCall();
});
}

    /**
     * Reject an incoming call
     */
    function rejectCall() {
    if (!currentCallData) return;

    // Send reject message
    sendWebSocketMessage({
    type: 'call_back',
    toUser: currentCallData.fromUser.toString(),
    fromUser: getCurrentUserId().toString(),
    msg: 'reject'
});

    // Stop ringtone
    stopCallSound();

    // Close the call modal
    closeCallModal();
}

    /**
     * Handle response to a call request
     */
    function handleCallResponse(message) {
    if (message.msg === 'accept') {
    // Call was accepted, create peer connection and send offer
    createPeerConnection();
    createOffer();
    document.getElementById('call-status').textContent = '已接通';
    isCallInProgress = true;

    // Start call timer
    startCallTimer();

    // Dispatch call-started event to initialize UI
    videoCallModal.dispatchEvent(new Event('call-started'));
} else if (message.msg === 'reject') {
    // Call was rejected
    showError('对方拒绝了通话');
    closeCallModal();
} else if (message.msg === 'busy') {
    // User is busy
    showError('对方正忙，请稍后再试');
    closeCallModal();
} else if (message.msg.includes('不在线')) {
    // User is offline
    showError('对方不在线，请稍后再试');
    closeCallModal();
}
}

    /**
     * Create and send an offer
     */
    function createOffer() {
    if (!peerConnection) return;

    peerConnection.createOffer()
    .then(offer => {
    return peerConnection.setLocalDescription(offer);
})
    .then(() => {
    // Send the offer to the remote peer
    sendWebSocketMessage({
    type: 'offer',
    toUser: currentCallData.toUser.toString(),
    fromUser: getCurrentUserId().toString(),
    sdp: peerConnection.localDescription.sdp
});
})
    .catch(error => {
    console.error('Error creating offer:', error);
});
}

    /**
     * Handle incoming WebRTC offer
     */
    function handleOffer(message) {
    if (!peerConnection) {
    createPeerConnection();
}

    // Set remote description
    const remoteDesc = new RTCSessionDescription({
    type: 'offer',
    sdp: message.sdp
});

    peerConnection.setRemoteDescription(remoteDesc)
    .then(() => {
    return peerConnection.createAnswer();
})
    .then(answer => {
    return peerConnection.setLocalDescription(answer);
})
    .then(() => {
    // Send the answer to the remote peer
    sendWebSocketMessage({
    type: 'answer',
    toUser: currentCallData.fromUser.toString(),
    fromUser: getCurrentUserId().toString(),
    sdp: peerConnection.localDescription.sdp
});

    isCallInProgress = true;

    // Update UI
    document.getElementById('call-status').textContent = '已接通';

    // Start call timer
    startCallTimer();
})
    .catch(error => {
    console.error('Error handling offer:', error);
});
}

    /**
     * Handle incoming WebRTC answer
     */
    function handleAnswer(message) {
    const remoteDesc = new RTCSessionDescription({
    type: 'answer',
    sdp: message.sdp
});

    peerConnection.setRemoteDescription(remoteDesc)
    .catch(error => {
    console.error('Error setting remote description:', error);
});
}

    /**
     * Handle incoming ICE candidate
     */
    function handleIceCandidate(message) {
    if (!peerConnection) return;

    const candidate = new RTCIceCandidate({
    sdpMLineIndex: message.sdpMLineIndex,
    sdpMid: message.sdpMid,
    candidate: message.candidate
});

    peerConnection.addIceCandidate(candidate)
    .catch(error => {
    console.error('Error adding ICE candidate:', error);
});
}

    /**
     * Handle call hangup
     */
    function handleHangup(message) {
    showError('对方已结束通话');
    closeCallModal();
}

    /**
     * End the current call
     */
    function endCall() {
    if (!currentCallData) return;

    // Send hangup message
    sendWebSocketMessage({
    type: 'hangup',
    toUser: isCallInProgress ?
    (currentCallData.toUser === getCurrentUserId() ? currentCallData.fromUser : currentCallData.toUser).toString() :
    currentCallData.toUser.toString(),
    fromUser: getCurrentUserId().toString()
});

    closeCallModal();
}

    /**
     * Close the call modal and clean up resources
     */
    function closeCallModal() {
    // If screen sharing is active, restore camera stream
    if (isScreenSharing && cameraStream) {
    isScreenSharing = false;

    // Stop screen sharing tracks
    if (localStream) {
    localStream.getTracks().forEach(track => track.stop());
}

    // Restore UI
    const screenShareBtn = document.getElementById('toggle-screen-share');
    if (screenShareBtn) {
    screenShareBtn.innerHTML = '<i class="fas fa-desktop"></i>';
    screenShareBtn.title = '屏幕共享';
    screenShareBtn.classList.remove('active');
}

    // Reset camera stream
    localStream = cameraStream;
    cameraStream = null;
}

    // Stop all tracks
    if (localStream) {
    localStream.getTracks().forEach(track => track.stop());
    localStream = null;
}

    // Close peer connection
    if (peerConnection) {
    peerConnection.close();
    peerConnection = null;
}

    // Reset call data
    currentCallData = null;
    isCallInProgress = false;

    // Stop timer
    stopCallTimer();

    // Stop any sounds
    stopCallSound();

    // Hide the modal and remove any specific call type classes
    videoCallModal.classList.remove('active');
    videoCallModal.classList.remove('voice-call');
    videoCallModal.classList.remove('active-call');
    videoCallModal.classList.remove('screen-sharing');

    // Clear video elements
    if (localVideo) {
    localVideo.srcObject = null;
}
    if (remoteVideo) {
    remoteVideo.srcObject = null;
}

    // Dispatch call-ended event
    videoCallModal.dispatchEvent(new Event('call-ended'));

    // Stop all control timers and resets
    clearControlsTimer();
    resetFullscreen();
    resetVideoSwap();
}

    /**
     * Get user media (camera and microphone)
     */
    function getUserMedia() {
    return navigator.mediaDevices.getUserMedia({
    audio: true,
    video: true
})
    .then(stream => {
    localStream = stream;
    localVideo.srcObject = stream;
    return stream;
});
}

    /**
     * Create WebRTC peer connection
     */
    function createPeerConnection() {
    if (peerConnection) {
    peerConnection.close();
}

    peerConnection = new RTCPeerConnection(configuration);

    // Add local stream tracks to the connection
    if (localStream) {
    localStream.getTracks().forEach(track => {
    peerConnection.addTrack(track, localStream);
});
}

    // Set up event handlers for the peer connection
    peerConnection.ontrack = function(event) {
    if (event.streams && event.streams[0]) {
    remoteStream = event.streams[0];
    remoteVideo.srcObject = remoteStream;
}
};

    peerConnection.onicecandidate = function(event) {
    if (event.candidate) {
    sendWebSocketMessage({
    type: '_ice',
    toUser: (currentCallData.toUser === getCurrentUserId() ? currentCallData.fromUser : currentCallData.toUser).toString(),
    fromUser: getCurrentUserId().toString(),
    sdpMid: event.candidate.sdpMid,
    sdpMLineIndex: event.candidate.sdpMLineIndex,
    candidate: event.candidate.candidate
});
}
};

    peerConnection.oniceconnectionstatechange = function() {
    console.log('ICE connection state:', peerConnection.iceConnectionState);

    if (peerConnection.iceConnectionState === 'disconnected' ||
    peerConnection.iceConnectionState === 'failed' ||
    peerConnection.iceConnectionState === 'closed') {
    showError('通话连接已断开');
    closeCallModal();
}
};

    return peerConnection;
}

    /**
     * Toggle microphone mute state
     */
    function toggleMicrophone() {
    if (!localStream) return;

    const audioTracks = localStream.getAudioTracks();
    if (audioTracks.length === 0) return;

    const isEnabled = audioTracks[0].enabled;
    audioTracks[0].enabled = !isEnabled;

    // Update button UI
    const micButton = document.getElementById('toggle-mic');
    if (isEnabled) {
    micButton.innerHTML = '<i class="fas fa-microphone-slash"></i>';
    micButton.title = '取消静音';
    micButton.classList.add('disabled');
} else {
    micButton.innerHTML = '<i class="fas fa-microphone"></i>';
    micButton.title = '静音';
    micButton.classList.remove('disabled');
}
}

    /**
     * Toggle video enable/disable
     */
    function toggleVideo() {
    if (!localStream) return;

    const videoTracks = localStream.getVideoTracks();
    if (videoTracks.length === 0) return;

    const isEnabled = videoTracks[0].enabled;
    videoTracks[0].enabled = !isEnabled;

    // Update button UI
    const videoButton = document.getElementById('toggle-video');
    if (isEnabled) {
    videoButton.innerHTML = '<i class="fas fa-video-slash"></i>';
    videoButton.title = '开启视频';
    videoButton.classList.add('disabled');
} else {
    videoButton.innerHTML = '<i class="fas fa-video"></i>';
    videoButton.title = '关闭视频';
    videoButton.classList.remove('disabled');
}
}

    /**
     * Switch between front and back camera (for mobile devices)
     */
    function switchCamera() {
    if (!localStream) return;

    // Get current video track
    const videoTrack = localStream.getVideoTracks()[0];
    if (!videoTrack) return;

    // Get current constraints
    const constraints = videoTrack.getConstraints();

    // Toggle facingMode
    const newFacingMode = constraints.facingMode === 'user' ? 'environment' : 'user';

    // Apply new constraints
    navigator.mediaDevices.getUserMedia({
    video: { facingMode: newFacingMode },
    audio: true
})
    .then(stream => {
    // Replace tracks in local stream
    const newVideoTrack = stream.getVideoTracks()[0];
    const newAudioTrack = stream.getAudioTracks()[0];

    if (newVideoTrack) {
    localStream.removeTrack(videoTrack);
    localStream.addTrack(newVideoTrack);

    // Replace track in peer connection
    const senders = peerConnection.getSenders();
    const videoSender = senders.find(sender => sender.track && sender.track.kind === 'video');
    if (videoSender) {
    videoSender.replaceTrack(newVideoTrack);
}

    // Update local video
    localVideo.srcObject = localStream;
}

    // Clean up unused track
    stream.getAudioTracks().forEach(track => track.stop());
})
    .catch(error => {
    console.error('Error switching camera:', error);
    showError('切换摄像头失败');
});
}

    /**
     * Send message through WebSocket
     */
    function sendWebSocketMessage(message) {
    if (!socket || socket.readyState !== WebSocket.OPEN) {
    console.error('WebSocket not connected');
    return;
}

    socket.send(JSON.stringify(message));
}

    /**
     * Start call timer
     */
    let callTimer = null;
    let callStartTime = null;

    function startCallTimer() {
    if (callTimer) {
    clearInterval(callTimer);
}

    callStartTime = new Date();
    const timerElement = document.getElementById('call-timer');

    callTimer = setInterval(() => {
    const now = new Date();
    const diff = now - callStartTime;

    const minutes = Math.floor(diff / 60000);
    const seconds = Math.floor((diff % 60000) / 1000);

    timerElement.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}, 1000);
}

    /**
     * Stop call timer
     */
    function stopCallTimer() {
    if (callTimer) {
    clearInterval(callTimer);
    callTimer = null;
}
}

    /**
     * Play call sound
     */
    let callSound = null;

    function playCallSound(type) {
    stopCallSound();

    try {
    // Due to the limitation of not being able to upload real sound files,
    // we'll use some fallback approach
    const soundPath = type === 'incoming' ?
    '/sounds/incoming-call.mp3' : '/sounds/outgoing-call.mp3';

    // First try to load the sound
    fetch(soundPath)
    .then(response => {
    if (response.ok) {
    callSound = new Audio(soundPath);
    callSound.loop = true;
    callSound.volume = 0.5;
    callSound.play().catch(e => {
    console.log('Could not play call sound:', e);
    useBeepFallback(type);
});
} else {
    useBeepFallback(type);
}
})
    .catch(error => {
    console.log('Error fetching sound file:', error);
    useBeepFallback(type);
});
} catch (error) {
    console.log('Sound playback error (safely handled):', error);
    useBeepFallback(type);
}
}

    /**
     * Use Web Audio API to generate beep sound as fallback
     */
    function useBeepFallback(type) {
    try {
    const audioContext = new (window.AudioContext || window.webkitAudioContext)();
    const oscillator = audioContext.createOscillator();
    const gainNode = audioContext.createGain();

    // Configure frequency and pattern based on call type
    const frequency = type === 'incoming' ? 880 : 440;
    const intervalTime = type === 'incoming' ? 1000 : 2000;

    oscillator.type = 'sine';
    oscillator.frequency.value = frequency;
    oscillator.connect(gainNode);
    gainNode.connect(audioContext.destination);

    // Start sound
    oscillator.start();

    // Create beep pattern
    let isOn = true;
    gainNode.gain.value = 0.2;

    // Store reference to interval for cleanup
    const beepInterval = setInterval(() => {
    isOn = !isOn;
    gainNode.gain.value = isOn ? 0.2 : 0;
}, intervalTime / 2);

    // Store in the callSound variable for cleanup
    callSound = {
    _oscillator: oscillator,
    _gainNode: gainNode,
    _interval: beepInterval,
    _audioContext: audioContext,

    // Custom stop method for our fallback
    pause: function() {
    clearInterval(this._interval);
    this._oscillator.stop();
    this._audioContext.close();
}
};
} catch (error) {
    console.log('Beep fallback failed:', error);
}
}

    /**
     * Stop call sound
     */
    function stopCallSound() {
    if (callSound) {
    if (typeof callSound.pause === 'function') {
    callSound.pause();
    if (callSound.currentTime !== undefined) {
    callSound.currentTime = 0;
}
}
    callSound = null;
}
}

    /**
     * Show error message
     */
    function showError(message) {
    // Create toast notification
    const toast = document.createElement('div');
    toast.className = 'video-call-toast';
    toast.textContent = message;

    document.body.appendChild(toast);

    // Show and then hide after 3 seconds
    setTimeout(() => {
    toast.classList.add('show');
}, 100);

    setTimeout(() => {
    toast.classList.remove('show');
    setTimeout(() => toast.remove(), 300);
}, 3000);
}

    /**
     * Get current user ID (uses the function from messages.js)
     */
    function getCurrentUserId() {
    if (window.currentUserId) {
    return window.currentUserId;
}

    if (window.getCurrentUserId && typeof window.getCurrentUserId === 'function') {
    return window.getCurrentUserId();
}

    const userData = JSON.parse(sessionStorage.getItem('user'));
    if (userData && userData.id) {
    return userData.id;
}

    console.error('Failed to get current user ID');
    return null;
}

    // Helper functions from messages.js
    function getSenderAvatar(senderId) {
    if (window.getSenderAvatar && typeof window.getSenderAvatar === 'function') {
    return window.getSenderAvatar(senderId);
}

    const contact = window.messageContacts ?
    window.messageContacts.find(c => c.id == senderId) : null;

    if (contact && contact.avatar) {
    return contact.avatar;
}

    return '/images/avatar.png';
}

    function getSenderName(senderId) {
    if (window.getSenderName && typeof window.getSenderName === 'function') {
    return window.getSenderName(senderId);
}

    const contact = window.messageContacts ?
    window.messageContacts.find(c => c.id == senderId) : null;

    return contact ? contact.name : `User ${senderId}`;
}

    /**
     * Toggle screen sharing
     */
    let isScreenSharing = false;
    let cameraStream = null; // Store camera stream to revert back after screen sharing ends

    function toggleScreenShare() {
    if (!peerConnection || !localStream) {
    showError('无法启动屏幕共享，请先确保连接已建立');
    return;
}

    const screenShareBtn = document.getElementById('toggle-screen-share');

    if (isScreenSharing) {
    // Stop screen sharing and revert to camera
    stopScreenSharing();
    screenShareBtn.innerHTML = '<i class="fas fa-desktop"></i>';
    screenShareBtn.title = '屏幕共享';
    screenShareBtn.classList.remove('active');
} else {
    // Start screen sharing
    startScreenSharing()
    .then(() => {
    screenShareBtn.innerHTML = '<i class="fas fa-user"></i>';
    screenShareBtn.title = '停止共享';
    screenShareBtn.classList.add('active');
})
    .catch(error => {
    console.error('Error starting screen sharing:', error);
    if (error.name === 'NotAllowedError') {
    showError('您取消了屏幕共享');
} else {
    showError('无法启动屏幕共享: ' + error.message);
}
});
}
}

    /**
     * Start screen sharing
     */
    async function startScreenSharing() {
    try {
    // Save current camera stream for later
    cameraStream = localStream;

    // Get screen sharing stream
    const screenStream = await navigator.mediaDevices.getDisplayMedia({
    video: {
    cursor: 'always',
    displaySurface: 'monitor',
},
    audio: true
});

    // Handle the stream ending (user stops sharing)
    screenStream.getVideoTracks()[0].addEventListener('ended', () => {
    stopScreenSharing();
    const screenShareBtn = document.getElementById('toggle-screen-share');
    screenShareBtn.innerHTML = '<i class="fas fa-desktop"></i>';
    screenShareBtn.title = '屏幕共享';
    screenShareBtn.classList.remove('active');
});

    // Replace local stream with screen stream
    localStream = screenStream;
    localVideo.srcObject = screenStream;

    // Add screen sharing CSS class
    videoCallModal.classList.add('screen-sharing');

    // Replace tracks in peer connection
    const senders = peerConnection.getSenders();
    const videoSender = senders.find(sender => sender.track && sender.track.kind === 'video');
    if (videoSender) {
    videoSender.replaceTrack(screenStream.getVideoTracks()[0]);
}

    // Set screen sharing flag
    isScreenSharing = true;

    // Show a notification to the remote user
    sendWebSocketMessage({
    type: 'notification',
    toUser: (currentCallData.toUser === getCurrentUserId() ? currentCallData.fromUser : currentCallData.toUser).toString(),
    fromUser: getCurrentUserId().toString(),
    msg: 'screen_sharing_started'
});

} catch (error) {
    console.error('Error starting screen sharing:', error);
    throw error;
}
}

    /**
     * Stop screen sharing
     */
    function stopScreenSharing() {
    if (!isScreenSharing || !cameraStream) return;

    try {
    // Stop all screen sharing tracks
    localStream.getTracks().forEach(track => track.stop());

    // Restore camera stream
    localStream = cameraStream;
    localVideo.srcObject = cameraStream;

    // Remove screen sharing CSS class
    videoCallModal.classList.remove('screen-sharing');

    // Replace tracks in peer connection
    const senders = peerConnection.getSenders();
    const videoSender = senders.find(sender => sender.track && sender.track.kind === 'video');
    if (videoSender && localStream.getVideoTracks().length > 0) {
    videoSender.replaceTrack(localStream.getVideoTracks()[0]);
}

    // Reset screen sharing flag
    isScreenSharing = false;

    // Show a notification to the remote user
    sendWebSocketMessage({
    type: 'notification',
    toUser: (currentCallData.toUser === getCurrentUserId() ? currentCallData.fromUser : currentCallData.toUser).toString(),
    fromUser: getCurrentUserId().toString(),
    msg: 'screen_sharing_stopped'
});

} catch (error) {
    console.error('Error stopping screen sharing:', error);
    showError('停止屏幕共享时出错');
}
}

    // Public API
    return {
    init: init,
    initiateVideoCall: initiateVideoCall,
    initiateVoiceCall: initiateVoiceCall
};
})();

    // Initialize when authentication is complete
    document.addEventListener('DOMContentLoaded', function() {
    const userData = JSON.parse(sessionStorage.getItem('user'));
    if (userData && userData.id) {
    videoChatModule.init(userData.id);
} else {
    // If user data isn't available yet, wait for auth.js to process
    document.addEventListener('user-authenticated', function(e) {
    if (e.detail && e.detail.userId) {
    videoChatModule.init(e.detail.userId);
}
});
}
});
